<?php

/**
 * User model.
 *
 * @package    sfDoctrineGuardPlugin
 * @subpackage model
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
 * @version    SVN: $Id: PluginsfGuardUser.class.php 25605 2009-12-18 18:55:55Z Jonathan.Wage $
 */
abstract class PluginsfGuardUser extends BasesfGuardUser
{
  protected
    $_groups         = null,
    $_permissions    = null,
    $_allPermissions = null;

  /**
   * Returns the string representation of the object: "Full Name (username)"
   *
   * @return string
   */
  public function __toString()
  {
    return (string) $this->getName().' ('.$this->getUsername().')';
  }

  /**
   * Returns the first and last name of the user concatenated together
   *
   * @return string $name
   */
  public function getName()
  {
    return trim($this->getFirstName().' '.$this->getLastName());
  }

  /**
   * Sets the user password.
   *
   * @param string $password
   */
  public function setPassword($password)
  {
    if (!$password && 0 == strlen($password))
    {
      return;
    }

    if (!$salt = $this->getSalt())
    {
      $salt = md5(rand(100000, 999999).$this->getUsername());
      $this->setSalt($salt);
    }
    $modified = $this->getModified();
    if ((!$algorithm = $this->getAlgorithm()) || (isset($modified['algorithm']) && $modified['algorithm'] == $this->getTable()->getDefaultValueOf('algorithm')))
    {
      $algorithm = sfConfig::get('app_sf_guard_plugin_algorithm_callable', 'sha1');
    }
    $algorithmAsStr = is_array($algorithm) ? $algorithm[0].'::'.$algorithm[1] : $algorithm;
    if (!is_callable($algorithm))
    {
      throw new sfException(sprintf('The algorithm callable "%s" is not callable.', $algorithmAsStr));
    }
    $this->setAlgorithm($algorithmAsStr);

    $this->_set('password', call_user_func_array($algorithm, array($salt.$password)));
  }

  /**
   * Returns whether or not the given password is valid.
   *
   * @param string $password
   * @return boolean
   */
  public function checkPassword($password)
  {
    if ($callable = sfConfig::get('app_sf_guard_plugin_check_password_callable'))
    {
      return call_user_func_array($callable, array($this->getUsername(), $password, $this));
    }
    else
    {
      return $this->checkPasswordByGuard($password);
    }
  }

  /**
   * Returns whether or not the given password is valid.
   *
   * @param string $password
   * @return boolean
   * @throws sfException
   */
  public function checkPasswordByGuard($password)
  {
    $algorithm = $this->getAlgorithm();
    if (false !== $pos = strpos($algorithm, '::'))
    {
      $algorithm = array(substr($algorithm, 0, $pos), substr($algorithm, $pos + 2));
    }
    if (!is_callable($algorithm))
    {
      throw new sfException(sprintf('The algorithm callable "%s" is not callable.', $algorithm));
    }

    return $this->getPassword() == call_user_func_array($algorithm, array($this->getSalt().$password));
  }

  /**
   * Adds the user a new group from its name.
   *
   * @param string $name The group name
   * @param Doctrine_Connection $con A Doctrine_Connection object
   * @throws sfException
   */
  public function addGroupByName($name, $con = null)
  {
    $group = Doctrine_Core::getTable('sfGuardGroup')->findOneByName($name);
    if (!$group)
    {
      throw new sfException(sprintf('The group "%s" does not exist.', $name));
    }

    $ug = new sfGuardUserGroup();
    $ug->setUser($this);
    $ug->setGroup($group);

    $ug->save($con);
  }

  /**
   * Adds the user a permission from its name.
   *
   * @param string $name The permission name
   * @param Doctrine_Connection $con A Doctrine_Connection object
   * @throws sfException
   */
  public function addPermissionByName($name, $con = null)
  {
    $permission = Doctrine_Core::getTable('sfGuardPermission')->findOneByName($name);
    if (!$permission)
    {
      throw new sfException(sprintf('The permission "%s" does not exist.', $name));
    }

    $up = new sfGuardUserPermission();
    $up->setUser($this);
    $up->setPermission($permission);

    $up->save($con);
  }

  /**
   * Checks whether or not the user belongs to the given group.
   *
   * @param string $name The group name
   * @return boolean
   */
  public function hasGroup($name)
  {
    $this->loadGroupsAndPermissions();
    return isset($this->_groups[$name]);
  }

  /**
   * Returns all related groups names.
   *
   * @return array
   */
  public function getGroupNames()
  {
    $this->loadGroupsAndPermissions();
    return array_keys($this->_groups);
  }

  /**
   * Returns whether or not the user has the given permission.
   *
   * @return boolean
   */
  public function hasPermission($name)
  {
    $this->loadGroupsAndPermissions();
    return isset($this->_allPermissions[$name]);
  }

  /**
   * Returns an array of all user's permissions names.
   *
   * @return array
   */
  public function getPermissionNames()
  {
    $this->loadGroupsAndPermissions();
    return array_keys($this->_allPermissions);
  }

  /**
   * Returns an array containing all permissions, including groups permissions
   * and single permissions.
   *
   * @return array
   */
  public function getAllPermissions()
  {
    if (!$this->_allPermissions)
    {
      $this->_allPermissions = array();
      $permissions = $this->getPermissions();
      foreach ($permissions as $permission)
      {
        $this->_allPermissions[$permission->getName()] = $permission;
      }

      foreach ($this->getGroups() as $group)
      {
        foreach ($group->getPermissions() as $permission)
        {
          $this->_allPermissions[$permission->getName()] = $permission;
        }
      }
    }

    return $this->_allPermissions;
  }

  /**
   * Returns an array of all permission names.
   *
   * @return array
   */
  public function getAllPermissionNames()
  {
    return array_keys($this->getAllPermissions());
  }

  /**
   * Loads the user's groups and permissions.
   *
   */
  public function loadGroupsAndPermissions()
  {
    $this->getAllPermissions();
    
    if (!$this->_permissions)
    {
      $permissions = $this->getPermissions();
      foreach ($permissions as $permission)
      {
        $this->_permissions[$permission->getName()] = $permission;
      }
    }
    
    if (!$this->_groups)
    {
      $groups = $this->getGroups();
      foreach ($groups as $group)
      {
        $this->_groups[$group->getName()] = $group;
      }
    }
  }

  /**
   * Reloads the user's groups and permissions.
   */
  public function reloadGroupsAndPermissions()
  {
    $this->_groups         = null;
    $this->_permissions    = null;
    $this->_allPermissions = null;
  }

  /**
   * Sets the password hash.
   *
   * @param string $v
   */
  public function setPasswordHash($v)
  {
    if (!is_null($v) && !is_string($v))
    {
      $v = (string) $v;
    }

    if ($this->password !== $v)
    {
      $this->_set('password', $v);
    }
  }
  
  /**********************/
  public function getAbstract(){
        $abstract = array();
        $abstract['id'] = $this->getId();
        $abstract['name'] = $this->getFirstName()." ".$this->getLastName()." ".$this->getSecondLastName();
        $abstract['photo'] = $this->getMainPhotoId();
        return $abstract;
  }
 
        public function getWidgetsPositions($sectionName)
        {
               
                $q = Doctrine_Query::create()
                        ->select('w.widget_id, u.name, w.row_position, w.column_position, w.minimized')
                        ->from('WidgetPosition w')
                        ->leftJoin('w.widget u')
                        ->leftJoin('u.section s')
                        ->where('w.user_id = ? and s.name = ?',array($this->getId(),$sectionName));
                $widgets = $q->fetchArray();
               
                $q = Doctrine_Query::create()
                        ->select('w.widget_id, u.name, w.position')
                        ->from('SectionWidget w')
                        ->leftJoin('w.widget u')
                        ->leftJoin('w.section sw')
                        ->where('sw.name = ?',$sectionName);
//echo $q->getSqlQuery();
                return array_merge($widgets,$q->fetchArray());
        }
       
        public function friendRequest($receiver)
        {
                if($receiver instanceof sfGuardUser){
                        if(!$receiver->isFriend($this)){
                                $request = new FriendRequest();
                                $request->setReceiver($receiver);
                                $request->setRequester($this);
                                $request->save();      
                        }else throw new Exception(_("Already friends"));
                }else throw new Exception(_("Invalid user"));
                //echo $event['receiver']->getId();
                //echo $event->getCosa();
        }
       
        public function isFriend($user){
                $friend = Doctrine::getTable("AclUsersGroups")->find(array($user->getId(),$this->getMainGroupId()));
                return $friend instanceof aclUsersGroups;
               
        }
       
        public function touch(){
                $this->setLastActivity(date('Y-m-d H:i:s'));
                $this->save();
        }
       
        public function getPrivateMessages($page,$size,$directory){
                //Check if user can get this directory. If not, get user's main directory
                $directory = Doctrine::getTable("PrivateMessageDirectory")->find($directory);
                if($directory->getUserId() != $this->getId()){
                        $directory = $this->getMainPrivateMessagesDirectory();
                }
                //
                $q = Doctrine_Query::create()
            ->from('PrivateMessageDirectoryMessage p')
            ->where('private_message_directory_id = ?',$directory->getId());
                       
                $messages=array();
                $pager = new sfDoctrinePager('PrivateMessageDirectoryMessage',$size);
                $pager->setQuery($q);
               
                $pager->setPage($page);
               
                $pager->init();
                return $pager;
        }
       
        public function getFriendNews(){
        	$i18n = sfContext::getInstance()->getI18N();
                /*              select * from acl_users_groups
JOIN sf_guard_user on (user_id=id)
WHERE group_id = 1 and last_activity >= now() - interval 1 day*/
                $q = Doctrine_Query::create()
                        ->select('u.user_id,(now() - last_activity) as time')
                        ->from('aclUsersGroups u')
                        ->leftJoin('u.user uw')
                        ->where('u.group_id = ? AND last_activity >= now() - interval 1 day',$this->getMainGroupId());
                       
               
                $activities = array();
                $users = $q->execute();
               
                if($users->count()>0){
                        foreach($users as $user)
                        {
                                $activity = array();
                                $realUser = $user->getUser();
                                $activity['url'] = "profile";
                                $activity['id'] = $user->getUserId();
                                $activity['photo_id'] = $realUser->getMainPhotoId();
                                $activity['title'] = $realUser->getFirstName()." ".$realUser->getLastName()." ".$realUser->getSecondLastName();
                                $activity['time'] = (int)$user->getTime();
                                $activity['events'] = array();
                               
                                //Blog
                                $blog = Doctrine_Query::create()
                                        ->select('u.blog_id')
                                        ->from('Blog u')
                                        ->where('u.profile_id = ? AND created_at >= now() - interval 1 day',$user->getUserId());
                                       
                                $blogs = $blog->execute();

                                if(($count = $blogs->count()) > 0){
                                        $event = array();
                                        $event['url'] = "profile";
                                        $event['id'] = $user->getUserId();
                                        $event['content'] =$count." ".$i18n->__("blog entry");
                                        $event['icon'] = "comment";
                                        $activity['events'][] = $event;
                                }
                                //Profile comments
                                $comment = Doctrine_Query::create()
                                        ->select('u.profile_comment_id')
                                        ->from('ProfileComment u')
                                        ->where('u.owner_id = ? AND created_at >= now() - interval 1 day',$user->getUserId());
                                $comments = $comment->execute();
                                if(($count = $comments->count()) > 0){
                                        $event = array();
                                        $event['url'] = "profile";
                                        $event['id'] = $user->getUserId();
                                        $event['content'] =$count." ".$i18n->__("comments");
                                        $event['icon'] = "person";
                                        $activity['events'][] = $event;
                                }
                                //Photos
                                $event = array();
                                $event['extra'] = "";
                                $nRealPhotos = 0;
                                $photos = array();
                                $photoQuery = Doctrine_Manager::getInstance()
                                        ->getCurrentConnection()
                                        ->fetchAssoc("SELECT photo_id from photo WHERE owner_id = ? AND created_at >= now() - interval 1 day",array($user->getUserId()));


                                $nTotalPhotos = count($photoQuery);
                                $nPhotosToShow = $nTotalPhotos>4?4:$nTotalPhotos;
                                for($i=0; $i<$nPhotosToShow; $i++){
                                        try{
                                                $photoId = $photoQuery[$i];
                                                $actualPhoto = Doctrine::getTable("Photo")->find($photoId['photo_id']);
                                                $event['extra'] .='<a href="#photo/loadPhoto/id/'.$actualPhoto->getPhotoId().'"><img src="/core.php/photo/thumbnail/id/'.$actualPhoto->getPhotoId().'/type/mini" class="ui-state-default ui-corner-all"></a>&nbsp;';
                                                $nRealPhotos++;
                                        }catch(AclException $e){
                                                //forbidden photo!
                                                if($nTotalPhotos-1 > $nPhotosToShow)
                                                        $nPhotosToShow++;
                                        }
                                }
                                if($nRealPhotos > 0){
                                        $event['url'] = "album";
                                        $event['id'] = $user->getUser()->getMainAlbumId();
                                        $event['icon'] = "image";
                                        $event['content'] =$nRealPhotos." ".$i18n->__("new photos");
                                        $event['extra'] = "<div>".$event['extra']."</div>";
                                        $activity['events'][] = $event;
                                }

                               
                                //Friends
                                $friend = Doctrine_Query::create()
                                        ->select('u.user_id')
                                        ->from('AclUsersGroups u')
                                        ->where('u.group_id = ? AND created_at >= now() - interval 1 day',$realUser->getMainGroupId());

                                foreach($friend->execute() as $friend){
                                        $realFriend = $friend->getUser();
                                        $event = array();
                                        $event['url'] = "profile";
                                        $event['id'] = $realFriend->getId();
                                        $event['content'] =$i18n->__("New friend").": ". $realFriend->getFirstName()." ".$realFriend->getLastName()." ".$realFriend->getSecondLastName();
                                        $event['icon'] = "person";
                                        $activity['events'][] = $event;
                                }
                               
                                $activities[] = $activity;
                               
                        }
                }
                return($activities);
        }
       
        public function getPhotoNews(){
                   $i18n = sfContext::getInstance()->getI18N();    
                //Photos where you are tagger and your own photos
                                $photos = array();
                                $photoQuery = Doctrine_Manager::getInstance()
                                        ->getCurrentConnection()
                                        ->fetchAssoc("SELECT photo_id,(now() - last_activity) as time from photo_tag join photo using(photo_id) WHERE user_id = ? AND photo_tag.created_at >= now() - interval 1 day",array($this->getId()));

                                foreach($photoQuery as $photo){
                                        try{
                                                $actualPhoto = Doctrine::getTable("Photo")->find($photo['photo_id']);
                                                $photoActivity = array();
                                                $photoActivity['time'] = $photo['time'];
                                                $photoActivity['photo'] = $actualPhoto;
                                                $photos[] = $photoActivity;
                                        }catch(AclException $e){
                                                //forbidden photo!
                                        }
                                }
                                     
                $activities = array();
                if(count($photos)>0){
                        foreach($photos as $photoActivity)
                        {

                                $realPhoto = $photoActivity['photo'];
                                $activity['url'] = "photo/load/";
                                $activity['id'] = $realPhoto->getPhotoId();
                                $activity['photo_id'] = $realPhoto->getPhotoId();
                                $activity['title'] = $realPhoto->getTitle();
                                $activity['time'] = (int)$photo['time'];
                                $activity['events'] = array();
                               
                                //Tags
                                $tag = Doctrine_Query::create()
                                        ->select('u.photo_id')
                                        ->from('PhotoTag u')
                                        ->where('u.photo_id = ? AND created_at >= now() - interval 1 day',$realPhoto->getPhotoId());
                                       
                                $tags = $tag->execute();

                                if(($count = $tags->count()) > 0){
                                        $event = array();
                                        $event['url'] = "photo/load/";
                                        $event['id'] = $realPhoto->getPhotoId();
                                        $event['content'] =$count." ".$i18n->__("tags");
                                        $event['icon'] = "tag";
                                        $activity['events'][] = $event;
                                }
                               
                                //Comments
                                $comment = Doctrine_Query::create()
                                        ->select('u.photo_id')
                                        ->from('PhotoComment u')
                                        ->where('u.photo_id = ? AND created_at >= now() - interval 1 day',$realPhoto->getPhotoId());
                                $comments = $comment->execute();
                                if(($count = $comments->count()) > 0){
                                        $event = array();
                                        $event['url'] = "photo/load/";
                                        $event['id'] = $realPhoto->getPhotoId();
                                        $event['content'] =$count." ".$i18n->__("comments");
                                        $event['icon'] = "person";
                                        $activity['events'][] = $event;
                                }
                               
                                $activities[] = $activity;
                               
                        }
                }
                return($activities);
        }
       
        public function getTaskList($start,$end){
                $q = Doctrine_Query::create()
                                ->select('*')
                                ->from('calendarTask c')
                                ->where('c.user_id = ? and c.start >= ? and c.end <= ?',array($this->getId(),$start,$end));
                return $q->execute();
        }
  
        
	
		public function getAllowedAlbums(){
                                $albums = array();
                                $albumQuery = Doctrine_Manager::getInstance()
                                        ->getCurrentConnection()
                                        ->fetchAssoc("SELECT album_id from album WHERE owner_id = ?",array($this->getId()));

                                foreach($albumQuery as $album)
                                {
                                        try{
                                                $actualAlbum = Doctrine::getTable("Album")->find($album['album_id']);
                                                $albums[] = $actualAlbum;
                                        }catch(AclException $e){
                                                //forbidden album!
                                        }
                                }
                                return $albums;
		}
}
